//////////////////////////////////////////////
// TreeView.h
//
//////////////////////////////////////////////

/// Defines / macro --------------------------

#pragma once

/// Forward decl -----------------------------

namespace nkWinUi
{
	class Image ;
	class System ;
}

/// Includes ---------------------------------

// nkWinUi
#include "Component.h"

#include "../Dll/DllDefines.h"

// nkMemory
#include <NilkinsMemory/Containers/BufferCast.h>
#include <NilkinsMemory/Containers/String.h>

#include <NilkinsMemory/Pointers/UniquePtr.h>

// Standards
#include <functional>

/// Class ------------------------------------
	
namespace nkWinUi
{
	class DLL_WINUI_EXPORT TreeView : public Component
	{
		public :

			class DLL_WINUI_EXPORT Item
			{
				public :

					// Constructor, destructor
					Item () noexcept ;
					virtual ~Item () ;

					// Children
					Item* addChild (Item* child) ;
					Item* getChild (unsigned int index) const ;
					unsigned int getChildCount () const ;
					bool isParent () const ;
					void disavowChild (Item* child) ;

					// Text & icon
					void setText (nkMemory::StringView text) ;
					void setIcon (Image* image) ;
					nkMemory::StringView getText () const ;
					Image* getIcon () const ;

					// Parents
					void setParentTree (TreeView* parent) ;
					TreeView* getParentTree () const ;
					void setParentItem (Item* item) ;
					Item* getParentItem () const ;

					// Data
					void setAttachedData (void* data) ;
					void* getAttachedData () const ;

					// Flags
					bool getCollapsed () const ;
					virtual void setCollapsed (bool value) ;

					// Export
					void exportIntrospection (nkExport::Node* rootNode) ;

				protected :
						
					// Attributes
					// Children
					nkMemory::BufferCast<Item*> _children ;

					// Its text and icon
					nkMemory::String _text ;
					Image* _icon ;

					// Parents
					TreeView* _parentTree ;
					Item* _parentItem ;
					Item* _precedingItem ;

					// Data
					void* _attachedData ;

					// Flags
					bool _collapsed ;
			} ;
		
		public :
		
			// Constructor, destructor
			TreeView (System* system) noexcept ;
			virtual ~TreeView () ;

			// Getters
			Item* getItemFromData (void* data) const ;
			virtual Item* getSelectedItem () = 0 ;
			virtual Item* getItemAtAbsoluteCursor (nkMaths::Point absCoords) = 0 ;
			virtual Item* getItemAtRelativeCursor (nkMaths::Point relCoords) = 0 ;
			bool getSelectOnRightClick () const ;
			std::function<void (TreeView*)> getSelectionCallback () const ;

			// Setters
			void setSelectionOnRightClick (bool value) ;
			void setSelectionCallback (std::function<void (TreeView*)> value) ;

			// Items management
			virtual Item* insertItem (nkMemory::StringView text, void* data, Item* parent = nullptr) ;
			virtual void deleteItem (Item* toDelete, bool keepChildrenOnUpper = false) ;
			virtual void changeItemLabel (Item* toChange, nkMemory::StringView label) ;
			virtual void clearItems () ;
			void collapseAll (bool status) ;

			// Selection
			void selectItemFromItsData (void* data) ;
			virtual void selectItem (Item* item) = 0 ;
			void selectItemFromAbsoluteCursor (nkMaths::Point absCoords) ;
			void selectItemFromRelativeCursor (nkMaths::Point relCoords) ;

			// Import / Export
			virtual void exportIntrospection (nkExport::Node* rootNode) override ;
			virtual void importClassFromTree (nkExport::Node* rootNode) override ;

		public :

			// Statics
			static nkMemory::UniquePtr<TreeView> create (System* system = nullptr) ;

		protected :

			// Functions
			virtual Item* _allocateItem () const = 0 ;

		protected :

			// Attributes
			// List of items
			nkMemory::BufferCast<Item*> _items ;

			// Callbacks
			std::function<void (TreeView*)> _selectionCallback ;

			// Flags
			bool _selectOnRightClick ;
	} ;
}